#include "threadPool.h"
#include <iostream>
#include <string.h>
#include <unistd.h>
#define DEFAULT_MIN_THREADS 3
#define DEFAULT_MAX_THREADS 5
#define DEFAULT_QUEUE_CAPACITY 8
#define DEFAULT_INCREASE_NUM 2
// 工作线程
// 消费者
void *workThreadFunc(void *arg)
{

    // 线程分离
    pthread_detach(pthread_self());
    ThreadPool *pool = (ThreadPool *)arg;

    while (true)
    {
        // 核心目标:从任务队列取元素
        pthread_mutex_lock(&(pool->m_lock));
        while (pool->m_queueSize == 0)
        {
            // usleep(10000);
            // 如何知道队列不为空?等待条件变量
            pthread_cond_wait(&(pool->m_notempty), &(pool->m_lock));
            if (pool->m_exitNum > 0 && pool->m_aliveThreads > pool->m_minThreads)
            {
                // 存活线程数--
                (pool->m_aliveThreads)--;
                pool->m_exitNum--;
                // 解锁
                pthread_mutex_unlock(&(pool->m_lock));
                std::cout << pthread_self() << "exit" << std::endl;
                for (int idx = 0; idx < pool->m_maxThreads; idx++)
                {
                    if (pool->m_threadIds[idx] == pthread_self())
                    {
                        pool->m_threadIds[idx] = 0;
                        break;
                    }
                }
                // 线程退出
                pthread_exit(nullptr);
            }
        }

        // 程序执行到这里:说明队列有任务
        // 取任务队列的队头
        Task_t newTask;
        newTask.function = pool->m_queue[pool->m_queueFront].function;
        newTask.arg = pool->m_queue[pool->m_queueFront].arg;
        // 移动队头位置
        pool->m_queueFront = (pool->m_queueFront + 1) % pool->m_queueCapacity;
        // 任务队列的元素个数减1
        pool->m_queueSize--;

        // 解锁
        pthread_mutex_unlock(&(pool->m_lock));

        // 加锁
        pthread_mutex_lock(&(pool->m_busyLock));
        // 忙碌的线程数++
        pool->m_busyThreads++;
        // 解锁
        pthread_mutex_unlock(&(pool->m_busyLock));
        // 执行任务
        newTask.function(newTask.arg);

        // 加锁
        pthread_mutex_lock(&(pool->m_busyLock));
        // 忙碌的线程数--

        pool->m_busyThreads--;
        // 解锁
        pthread_mutex_unlock(&(pool->m_busyLock));

        // 发送信号 发送不满的信号
        pthread_cond_signal(&(pool->m_notfull));
    }
    // 线程退出
    pthread_exit(nullptr);
}

// 管理线程
void *managerThreadFunc(void *arg)
{
    // 线程分离
    pthread_detach(pthread_self());

    ThreadPool *pool = (ThreadPool *)arg;
    while (true)
    {
        sleep(1);
        int ret = 0;
        // 加锁
        pthread_mutex_lock(&(pool->m_lock));
        int queueSize = pool->m_queueSize;
        int aliveThreadNum = pool->m_aliveThreads;
        pthread_mutex_unlock(&(pool->m_lock));

        // 加锁
        pthread_mutex_lock(&(pool->m_busyLock));

        int busyThreadNum = pool->m_busyThreads;
        pthread_mutex_unlock(&(pool->m_busyLock));

        //std::cout << queueSize << " " << aliveThreadNum << " " << busyThreadNum << std::endl;

        // 什么时候需要开辟新的线程
        // 任务队列的任务数大于    存活线程数-忙碌线程数
        if ((queueSize > aliveThreadNum - busyThreadNum) && aliveThreadNum < pool->m_maxThreads)
        {
            int addCnt = 0;
            pthread_mutex_lock(&(pool->m_lock));
            for (int idx = 0; idx < (pool->m_maxThreads) && addCnt < DEFAULT_INCREASE_NUM; idx++)
            {
                if (pool->m_threadIds[idx] == 0)
                {
                    ret = pthread_create(&(pool->m_threadIds[idx]), NULL, workThreadFunc, pool);
                    if (ret == -1)
                    {
                        perror("thread create error");
                        break;
                    }
                    addCnt++;
                    // 存活线程数++
                    pool->m_aliveThreads++;
                }
            }
            // 解锁
            pthread_mutex_unlock(&(pool->m_lock));
        }
        // 什么时候需要减少线程池中的线程数量
        // 任务队列的任务数 远小于 存活线程数  减 忙碌线程数
        // 且保证存活线程数大于线程池最小线程数
        if (pool->m_queueSize < (aliveThreadNum - busyThreadNum) && aliveThreadNum > pool->m_minThreads)
        {
            // 加锁
            pthread_mutex_lock(&(pool->m_lock));
            pool->m_exitNum = DEFAULT_INCREASE_NUM;
            for (int idx = 0; idx < pool->m_exitNum; idx++)
            {
                pthread_cond_signal(&(pool->m_notempty));
            }
            // 解锁
            pthread_mutex_unlock(&(pool->m_lock));
        }
    }

    pthread_exit(NULL);
}

// 构造函数
ThreadPool::ThreadPool(int minThread, int maxThread, int maxQueueCapacity)
{
    // 参数校验
    if (minThread < 0 || maxThread < 0 || maxQueueCapacity < 0)
    {
        minThread = DEFAULT_MIN_THREADS;
        maxThread = DEFAULT_MAX_THREADS;
        maxQueueCapacity = DEFAULT_QUEUE_CAPACITY;
    }

    // 维护属性
    m_minThreads = minThread;
    m_maxThreads = maxThread;
    m_queueCapacity = maxQueueCapacity;
    m_aliveThreads = 0;
    m_busyThreads = 0;
    m_exitNum = 0;
    // 创建线程池空间
    try
    {
        m_threadIds = new pthread_t[maxThread];
        if (m_threadIds == NULL)
        {
            perror("new error!");
        }
        // 清除脏数据
        memset(m_threadIds, 0, sizeof(pthread_t) * maxThread);
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
    int ret = 0;

    // 创建队列
    m_queue = new Task_t[m_queueCapacity];
    if (m_queue == nullptr)
    {
        perror("new error!");
        exit(-1);
    }
    // 清除脏数据
    memset(m_queue, 0, sizeof(Task_t) * m_queueCapacity);
    // 任务队列的元素个数为0
    m_queueSize = 0;
    // 任务队列的队头
    m_queueFront = 0;
    // 任务队列的队尾
    m_queueRear = 0;

    // 初始化锁
    ret = pthread_mutex_init(&m_lock, NULL);
    if (ret != 0)
    {
        perror("mutex init error");
        exit(-1);
    }

    ret = pthread_mutex_init(&m_busyLock, NULL);
    if (ret != 0)
    {
        perror("busy mutex init error");
        exit(-1);
    }

    // 初始化条件变量
    ret = pthread_cond_init(&m_notempty, NULL);
    if (ret != 0)
    {
        perror("cond init error");
        exit(-1);
    }

    ret = pthread_cond_init(&m_notfull, NULL);
    if (ret != 0)
    {
        perror("cond init error");
        exit(-1);
    }

    // 创建最小的线程数
    for (int idx = 0; idx < m_minThreads; idx++)
    {
        ret = pthread_create(&m_threadIds[idx], NULL, workThreadFunc, this);
        if (ret == -1)
        {
            perror("thread create error!");
            exit(-1);
        }
        // 每创建完成一个线程,存活的线程数++
        m_aliveThreads++;
    }

    // 创建管理者线程
    ret = pthread_create(&m_managerId, NULL, managerThreadFunc, this);
    if (ret == -1)
    {
        perror("mannager thread create error!");
        exit(-1);
    }
}

// 添加任务
// 生产者
void ThreadPool::addTask(void *(*function)(void *arg), void *arg)
{
    if (function == nullptr)
    {
        return;
    }
    // 将任务添加到队列中

    // 加锁
    pthread_mutex_lock(&m_lock);

    // 任务个数达到上限
    while (m_queueSize == m_queueCapacity)
    {
        // 等待不满的条件变量
        pthread_cond_wait(&m_notfull, &m_lock);
    }

    // 程序执行到这里,说明队列有位置放
    m_queue[m_queueRear].function = function;
    m_queue[m_queueRear].arg = arg;
    // 更新队列尾部
    m_queueRear = (m_queueRear + 1) % m_queueCapacity;

    // 任务队列数加1
    m_queueSize++;
    // 解锁
    pthread_mutex_unlock(&m_lock);

    // 发信号
    pthread_cond_signal(&m_notempty);
}
